package org.springframework.samples.petclinic.web;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.Map;
import java.util.Random;

import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.samples.petclinic.model.Email;
import org.springframework.samples.petclinic.model.PetType;
import org.springframework.samples.petclinic.model.Sleep;
import org.springframework.samples.petclinic.model.Sleep.SleepType;
import org.springframework.samples.petclinic.service.ClinicService;
import org.springframework.samples.petclinic.util.SleepUtils;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.SessionAttributes;
import org.springframework.web.bind.support.SessionStatus;

import sun.security.provider.SHA;
import sun.security.provider.SHA2;

@Controller
@SessionAttributes(types = Sleep.class)
public class SleepController {
	
    private final ClinicService clinicService;
    private static Logger logger = LoggerFactory.getLogger(SleepController.class);

    @Autowired
    public SleepController(ClinicService clinicService) {
        this.clinicService = clinicService;
    }
    
    @ModelAttribute("types")
    public Collection<SleepType> populatePetTypes() {
        return Arrays.asList(SleepType.values());
    }

    @InitBinder
    public void setAllowedFields(WebDataBinder dataBinder) {
        dataBinder.setDisallowedFields("id");
    }

    @RequestMapping(value = "/sleep/new", method = RequestMethod.GET)
    public String initCreationForm(Map<String, Object> model) {
    	Sleep sleep = new Sleep();
        model.put("sleep", sleep);
        return "sleep/sleepForm";
    }

    @RequestMapping(value = "/sleep/new", method = RequestMethod.POST)
    public String processCreationForm(@Valid Sleep sleep, BindingResult result, SessionStatus status, HttpServletResponse response, Model model) throws InterruptedException, IOException {
    	if (result.hasErrors()) {
            return "/sleep/new";
        } else {
    	
        	switch (sleep.getType()) {
        		case THREAD_SLEEP : 
        			threadSleep(sleep.getSleepTime());
        			break;
        		case WAIT:
        			waitSleep(sleep.getSleepTime());
        			break;
        		case ACTIVE_LOOP:
        			activeLoopSleep(sleep.getSleepTime());
        			break;
        		case SOCKET_READ:
        			socketReadSleep(sleep.getSleepTime());
        			break;
        		case INTRINSIC_LOCK:
        			intrisicLock();
        			break;
        		case REENTRANT_LOCK:
        			reentrantLock();
        			break;
        		case ALL:
        			allSleep(sleep.getSleepTime());
        			break;
        		default:
        			throw new IllegalArgumentException("Unknown sleep type: " + sleep.getType());
        	}		
        		
        	
        	model.addAttribute("message", "<b>sleep" + sleep.getType() + " " + sleep.getSleepTime() + " finished</b><br/>");
            return "sleep/sleepForm" ;
        }
    }

	private void reentrantLock() {
		SleepUtils.reentrantLock();
	}

	private void intrisicLock() {
		SleepUtils.intrinsicLock();
	}

	private void allSleep(long sleepTime) throws InterruptedException, IOException {
		SleepUtils.allSleep(sleepTime);
	}

	private void socketReadSleep(long sleepTime) throws IOException {
		SleepUtils.socketReadSleep(sleepTime);
	}

	private void activeLoopSleep(long sleepTime) {
		SleepUtils.activeLoopSleep(sleepTime);
	}

	private void waitSleep(long sleepTime) throws InterruptedException {
		SleepUtils.waitSleep(sleepTime);
		
	}

	private void threadSleep(long sleepTime) throws InterruptedException {
		SleepUtils.threadSleep(sleepTime);
	}
}
